package com.liss.juc20211122.cf;

import lombok.Data;

import java.util.concurrent.*;
/**
 * 组合：
 * 合并：
 * 结果选用：
 * 结果消费：
 * 结果处理：
 * 获得结果和触发计算
 */

/**
 * 1.supplyAsync()
 */
public class CompletableFutureAPIDemo {
    public static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 20,
            1L, TimeUnit.SECONDS,new LinkedBlockingQueue<>(50), Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy());

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        m4();
    }

    /**
     * thenCompose（）用来连接两个CompletableFuture，是生成一个新的CompletableFuture。
     * @throws ExecutionException
     * @throws InterruptedException
     */
    public static void m6() throws ExecutionException, InterruptedException {
            CompletableFuture<Dept> future = CompletableFuture.supplyAsync(() -> {
            Dept dept = new Dept();
            dept.setId("1001");
            dept.setName("研发部");
            return dept;
        }).thenCompose(dept -> CompletableFuture.supplyAsync(() -> {
            dept.setName("产品部");
            return dept;
        },threadPoolExecutor));
        System.out.println("线程：" + Thread.currentThread().getName() +
                " 结果：" + future.get().toString());
    }
    /**
     * 结果进行合并：thenCombine()
     */
    public static void m5()
    {
        System.out.println(CompletableFuture.supplyAsync(() -> {
            return getNum(5);
//            return 2;
        }).thenCombine(CompletableFuture.supplyAsync(() -> {
            return getNum(2);
        }), (a, b) -> a + b).join());
    }

    private static Integer getNum(int i) {
        return i*2;
    }

    /**
     * 对计算速度进行选用
     */
    public static void m4()
    {
        System.out.println(CompletableFuture.supplyAsync(() -> {
            //暂停几秒钟线程
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 1;
        }).applyToEither(CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 2;
        }), r -> {
            return r;
        }).join());

        //暂停几秒钟线程
        try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
    }
    /**
     * 对计算结果进行消费
     */
    public static void m3()
    {
        CompletableFuture.supplyAsync(() -> {
            return 1;
        }).thenApply(f -> {
            return f+2;
        }).thenApply(f -> {
            return f+3;
        }).thenAccept(r -> System.out.println(r));


        System.out.println(CompletableFuture.supplyAsync(() -> "resultA").thenRun(() -> {}).join());


        System.out.println(CompletableFuture.supplyAsync(() -> "resultA").thenAccept(resultA -> {}).join());


        System.out.println(CompletableFuture.supplyAsync(() -> "resultA").thenApply(resultA -> resultA + " resultB").join());
    }
    /**
     * 对计算结果进行处理
     */
    public static void m2()
    {
        System.out.println(CompletableFuture.supplyAsync(() -> 1).handle((f, e) -> {
            System.out.println("-----1");
            return f + 2;
        }).handle((f,e) -> {
            System.out.println("-----2");
            return f + 3;
        }).handle((f,e) -> {
            System.out.println("-----3");
            return f + 4;
        }).whenComplete((v, e) -> {
            if (e == null) {
                System.out.println("----result: " + v);
            }
        }).exceptionally(e -> {
            e.printStackTrace();
            return null;
        }).join());


        threadPoolExecutor.shutdown();
    }
    /**
     * 获得结果和触发计算
     *
     * @throws InterruptedException
     * @throws ExecutionException
     */
    public static void m1() throws InterruptedException, ExecutionException {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 1;
        }, threadPoolExecutor);
        //暂停几秒钟线程
        try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
        //System.out.println(future.getNow(9999));
        System.out.println(future.complete(-44)+"\t"+future.get());
        threadPoolExecutor.shutdown();
    }
}

@Data
class Dept{
    private String id;
    private String name;
}